home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
-
- /*
- $Header: b3sou.c,v 1.4 85/08/22 16:59:08 timo Exp $
- */
-
- /* Sources: maintaining units and values on external files */
-
- #include "b.h"
- #include "b0con.h"
- #include "b0fea.h"
- #include "b0fil.h"
- #include "b1mem.h"
- #include "b1obj.h"
- #include "b2syn.h"
- #include "b2par.h"
- #include "b2nod.h"
- #include "b3env.h"
- #include "b3scr.h"
- #include "b3err.h"
- #include "b3sem.h"
- #include "b3fil.h"
- #include "b3sou.h"
- #include "b3int.h"
-
- /************************** UNITS ************************************/
-
- Hidden value b_perm; /* The table that maps tags to their file names */
- Hidden value b_units; /* The table that maps tags to their internal repr. */
-
- Hidden bool
- u_exists(pname, aa)
- value pname, **aa;
- {
- return in_env(b_units, pname, aa);
- }
-
- Visible Procedure
- def_unit(pname, u)
- value pname, u;
- {
- e_replace(u, &b_units, pname);
- }
-
- Hidden Procedure
- free_unit(pname)
- value pname;
- {
- e_delete(&b_units, pname);
- }
-
- Hidden Procedure
- del_units()
- {
- int len= length(b_units), k; how *u;
- for (k= len-1; k >= 0; --k) {
- /* Reverse loop so deletions don't affect the numbering! */
- u= How_to(*assoc(b_units, k));
- if (!u->unparsed) free_unit(*key(b_units, k));
- /*Therefore standard B functions must be entered as unparsed*/
- }
- }
-
- Visible Procedure
- rem_unit(u)
- parsetree u;
- {
- value pname= get_pname(u);
- free_unit(pname);
- release(pname);
- }
-
- /********************************************************************** */
-
- Visible Procedure
- p_name_type(pname, name, type)
- value pname, *name; literal *type;
- {
- *name= behead(pname, MkSmallInt(2));
- switch (strval(pname)[0]) {
- case '0': *type= Zer; break;
- case '1': *type= Mon; break;
- case '2': *type= Dya; break;
- case '3': *type= How; break;
- case '4': *type= Tar; break;
- default: syserr(MESS(4000, "p_name_type"));
- /* NOTREACHED */
- }
- }
-
- Visible value
- permkey(name, type)
- value name; literal type;
- {
- value v, w; string t;
- switch (type) {
- case Zer: t= "0"; break;
- case Mon: t= "1"; break;
- case Dya: t= "2"; break;
- case How: t= "3"; break;
- case Tar: t= "4"; break;
- default: syserr(MESS(4001, "wrong permkey"));
- }
- w= mk_text(t);
- v= concat(w, name); release(w);
- return v;
- }
-
- Visible bool
- p_exists(pname, aa)
- value pname, **aa;
- {
- return in_env(b_perm, pname, aa);
- }
-
- Visible value file_names;
-
- Hidden Procedure
- def_perm(pname, f)
- value pname, f;
- {
- e_replace(f, &b_perm, pname);
- if (!in(f, file_names)) insert(f, &file_names);
- }
-
- Hidden Procedure
- free_perm(pname)
- value pname;
- {
- value *aa;
- if (p_exists(pname, &aa)) {
- remove(*aa, &file_names);
- f_delete(*aa);
- e_delete(&b_perm, pname);
- }
- }
-
- Hidden value
- get_fname(pname)
- value pname;
- {
- value *aa;
- if (p_exists(pname, &aa)) return copy(*aa);
- else {
- value fname, name; literal type;
- p_name_type(pname, &name, &type);
- fname= new_fname(name, type);
- def_perm(pname, fname);
- release(name);
- return fname;
- }
- }
-
- Hidden bool
- p_version(name, type, pname)
- value name, *pname; literal type;
- {
- value *aa;
- *pname= permkey(name, type);
- if (p_exists(*pname, &aa)) return Yes;
- release(*pname); *pname= Vnil;
- return No;
- }
-
- Hidden bool
- how_unit(pname)
- value pname;
- {
- value name; literal type;
- p_name_type(pname, &name, &type);
- release(name);
- return type == How;
- }
-
- Hidden bool
- zermon_units(pname, other_pname)
- value pname, *other_pname;
- {
- value name; literal type; bool is;
- p_name_type(pname, &name, &type);
- is= (type == Zer && p_version(name, Mon, other_pname)) ||
- (type == Mon && p_version(name, Zer, other_pname));
- release(name);
- return is;
- }
-
- /***********************************************************************/
-
- Hidden bool
- is_loaded(pname, aa)
- value pname, **aa;
- {
- value u= Vnil, npname= Vnil, get_unit();
- if (u_exists(pname, aa)) return Yes; /* already loaded */
- if (!p_exists(pname, aa)) return No;
- ifile= fopen(strval(**aa), "r");
- if (ifile == NULL) {
- vs_ifile();
- return No;
- }
- Eof= No;
- first_ilev();
- u= get_unit(&npname, Yes);
- if (still_ok) def_unit(npname, u);
- fclose(ifile);
- vs_ifile();
- Eof= No;
- if (still_ok && !u_exists(pname, aa)) {
- value name; literal type;
- p_name_type(npname, &name, &type);
- release(uname); uname= copy(pname);
- curline= How_to(u)->unit; curlino= one;
- error2(MESS(4002, "filename and unit name incompatible for "), name);
- release(name);
- }
- release(u); release(npname);
- return still_ok;
- }
-
- /* Does the unit exist without faults? */
-
- Visible bool
- is_unit(name, type, aa)
- value name, **aa; literal type;
- {
- value pname;
- context c; bool is;
- sv_context(&c);
- cntxt= In_unit;
- pname= permkey(name, type);
- is= is_loaded(pname, aa);
- release(pname);
- set_context(&c);
- return is;
- }
-
- /***********************************************************************/
-
- Hidden char DISCARD[]= "the unit name is already in use;\n\
- *** should the old unit be discarded?";
-
- #define CANT_WRITE \
- MESS(4003, "cannot create file; need write permission in directory")
-
- #define CANT_READ MESS(4004, "unable to find file")
- #define MON_VERSION MESS(4005, " is already a monadic function/predicate")
- #define ZER_VERSION MESS(4006, " is already a zeroadic function/predicate")
-
- Hidden Procedure
- u_name_type(v, name, type)
- parsetree v; value *name; literal *type;
- {
- switch (Nodetype(v)) {
- case HOW_TO: *name= copy(*Branch(v, UNIT_NAME));
- *type= How;
- break;
- case YIELD:
- case TEST: *name= copy(*Branch(v, UNIT_NAME));
- switch (intval(*Branch(v, FPR_ADICITY))) {
- case 0: *type= Zer; break;
- case 1: *type= Mon; break;
- case 2: *type= Dya; break;
- default: syserr(MESS(4007, "wrong adicity"));
- }
- break;
- default: syserr(MESS(4008, "wrong nodetype of unit"));
- }
- }
-
- Hidden value
- get_unit(pname, filed)
- value *pname; bool filed;
- {
- value name; literal type;
- parsetree u= unit(No);
- if (u == NilTree) return Vnil;
- u_name_type(u, &name, &type);
- *pname= permkey(name, type);
- release(name);
- switch (Nodetype(u)) {
- case HOW_TO: return mk_how(u, filed);
- case YIELD: return mk_fun(type, Use, u, filed);
- case TEST: return mk_prd(type, Use, u, filed);
- default: syserr(MESS(4009, "wrong nodetype in 'get_unit'"));
- }
- /* NOTREACHED */
- }
-
- Visible value
- get_pname(v)
- parsetree v;
- {
- value pname, name; literal type;
- u_name_type(v, &name, &type);
- pname= permkey(name, type);
- release(name);
- return pname;
- }
-
- Hidden Procedure
- get_heading(h, pname)
- parsetree *h; value *pname;
- {
- *h= unit(Yes);
- *pname= still_ok ? get_pname(*h) : Vnil;
- }
-
- /* Create a unit via the editor or from the input stream */
-
- Visible Procedure
- create_unit()
- {
- value pname= Vnil, *aa; parsetree heading= NilTree;
- if (!interactive) {
- value v= get_unit(&pname, No);
- if (still_ok) def_unit(pname, v);
- release(v); release(pname);
- return;
- }
- get_heading(&heading, &pname);
- if (still_ok) {
- value v;
- if (p_exists(pname, &aa)) {
- if (is_intended(DISCARD)) {
- free_unit(pname);
- free_perm(pname);
- } else {
- tx= ceol;
- release(pname);
- release(heading);
- return;
- }
- } else if (zermon_units(pname, &v)) {
- value name; literal type;
- p_name_type(pname, &name, &type);
- curline= heading; curlino= one;
- error3(0, name, type == Zer ? MON_VERSION
- : ZER_VERSION);
- release(name); release(v);
- }
- }
- if (still_ok) {
- value fname= get_fname(pname);
- FILE *ofile= fopen(strval(fname), "w");
- if (ofile == NULL) error(CANT_WRITE);
- else {
- txptr tp= fcol();
- do { fputc(Char(tp), ofile); }
- while (Char(tp++) != '\n');
- f_close(ofile);
- ed_unit(pname, fname);
- }
- release(fname);
- }
- release(pname); release(heading);
- }
-
-
- /***********************************************************************/
-
- /* Edit a unit. The name of the unit is either given, or is defaulted
- to the last unit edited or the last unit that gave an error, whichever
- was most recent.
- It is possible for the user to mess things up with the w command, for
- instance, but this is not checked. It is allowed to rename the unit though,
- or delete it completely. If the file is empty, the unit is disposed of.
- Otherwise, the name and adicity are determined and if these have changed,
- the new unit is written out to a new file, and the original written back.
- Thus the original is not lost.
-
- Renaming, deleting, or changing the adicity of a test or yield
- unfortunately requires all other units to be thrown away internally
- (by del_units), since the unit parse trees may be wrong. For instance,
- consider the effect on the following of making a formerly monadic
- function f, into a zeroadic function:
- WRITE f root 2
- */
-
- Hidden char ZEROADIC[]=
- "the unit name is in use both for a zeroadic and a dyadic version;\n\
- *** do you want to edit the zeroadic version?";
-
- Hidden char MONADIC[]=
- "the unit name is in use both for a monadic and a dyadic version;\n\
- *** do you want to edit the monadic version?";
-
- Visible Procedure
- edit_unit()
- {
- value name= Vnil, pname= Vnil, v= Vnil; bool ens_filed();
- value fname;
- if (Ceol(tx)) {
- if (erruname == Vnil) parerr(MESS(4010, "no current unit"));
- else pname= copy(erruname);
- } else if (is_keyword(&name))
- pname= permkey(name, How);
- else if (is_tag(&name)) {
- if (p_version(name, Zer, &pname)) {
- if (p_version(name, Dya, &v) && !is_intended(ZEROADIC)) {
- release(pname); pname= copy(v);
- }
- } else if (p_version(name, Mon, &pname)) {
- if (p_version(name, Dya, &v) && !is_intended(MONADIC)) {
- release(pname); pname= copy(v);
- }
- } else {
- pname= permkey(name, Dya);
- }
- } else {
- parerr(MESS(4011, "I find nothing editible here"));
- }
- if (still_ok && ens_filed(pname, &fname)) {
- ed_unit(pname, fname);
- release(fname);
- }
- release(name); release(pname); release(v);
- }
-
- Hidden char NO_U_WRITE[]=
- "you have no write permission in this workspace: you may not change the unit\n\
- *** do you still want to display the unit?";
-
- Hidden char ZER_MON[]=
- "the unit name is already in use for a zeroadic function or predicate;\n\
- *** should that unit be discarded?\n\
- *** (if not you have to change the monadic unit name)";
-
- Hidden char MON_ZER[]=
- "the unit name is already in use for a monadic function or predicate;\n\
- *** should that unit be discarded?\n\
- *** (if not you have to change the zeroadic unit name)";
-
- Hidden Procedure
- ed_unit(pname, fname)
- value pname, fname;
- {
- value sname= Vnil, npname= Vnil, nfname= Vnil;
- value u, *aa, v= Vnil, v_free= Vnil;
- intlet err_line();
- bool new_def= Yes, same_name= No, still_there(), ed_again= No;
-
- if (!ws_writable() && !is_intended(NO_U_WRITE)) return;
- sname= f_save(fname); /* in case the unit gets renamed */
- if (sname == Vnil) {
- error(MESS(4012, "can't save to temporary file"));
- return;
- }
- release(uname); uname= copy(pname);
- #ifndef INTEGRATION
- f_edit(fname, err_line(pname));
- #else
- f_edit(fname, err_line(pname), unit_prompt);
- #endif
- if (!still_there(fname)) {
- free_unit(pname);
- if (!how_unit(pname)) del_units();
- release(erruname); erruname= Vnil; errlino= 0;
- free_perm(pname);
- f_delete(sname);
- release(sname);
- return;
- }
- first_ilev();
- u= get_unit(&npname, Yes);
- fclose(ifile); vs_ifile(); Eof= No;
- if (u == Vnil || npname == Vnil)
- new_def= No;
- else if (same_name= compare(pname, npname) == 0)
- new_def= p_exists(pname, &aa);
- else if (p_exists(npname, &aa))
- new_def= is_intended(DISCARD);
- else if (zermon_units(npname, &v)) {
- value name; literal type;
- p_name_type(npname, &name, &type);
- if (new_def= is_intended(type == Zer ? MON_ZER : ZER_MON)) {
- free_unit(v);
- v_free= copy(v); /* YIELD f => YIELD f x */
- } else {
- nfname= new_fname(name, type);
- f_rename(fname, nfname);
- ed_again= Yes;
- }
- release(name);
- }
- if (new_def) {
- if (!how_unit(npname)) del_units();
- if (still_ok) def_unit(npname, u);
- else free_unit(npname);
- if (!same_name) {
- nfname= get_fname(npname);
- f_rename(fname, nfname);
- if (v_free) free_perm(v_free);
- }
- release(erruname); erruname= copy(npname);
- }
- if (!same_name) f_rename(sname, fname);
- else f_delete(sname);
- if (!p_exists(pname, &aa)) f_delete(fname);
- if (ed_again) ed_unit(npname, nfname);
- release(npname); release(u); release(sname); release(nfname);
- release(v); release(v_free);
- }
-
- /* Find out if the file exists, and is not empty. Some wretched editors
- for some reason don't allow a file to be edited to empty, but insist it
- should be at least one empty line. Thus an initial empty line may be
- disregarded, but this is not harmful. */
-
- Hidden bool still_there(fname) value fname; {
- int k;
- ifile= fopen(strval(fname), "r");
- if (ifile == NULL) {
- vs_ifile();
- /* error(CANT_READ); */
- return No;
- } else {
- if ((k= getc(ifile)) == EOF || (k == '\n' && (k= getc(ifile)) == EOF)) {
- fclose(ifile);
- f_delete(fname);
- vs_ifile();
- return No;
- }
- ungetc(k, ifile);
- return Yes;
- }
- }
-
- /* Ensure the unit is filed. If the unit was read non-interactively (eg passed
- as a parameter to b), it is only held in store.
- Editing it puts it into a file. This is the safest way to copy a unit from
- one workspace to another.
- */
-
- Hidden bool
- ens_filed(pname, fname)
- value pname, *fname;
- {
- value *aa;
- if (p_exists(pname, &aa)) {
- *fname= copy(*aa);
- return Yes;
- } else if (!u_exists(pname, &aa) || How_to(*aa)->unit == NilTree) {
- pprerr(MESS(4013, "no such unit in this workspace"));
- return No;
- } else {
- how *du= How_to(*aa); FILE *ofile;
- if (du->filed == Yes) {
- syserr(MESS(4014, "ens_filed()"));
- return No;
- }
- *fname= get_fname(pname);
- ofile= fopen(strval(*fname), "w");
- if (!ofile) {
- error(CANT_WRITE);
- release(*fname);
- return No;
- } else {
- display(ofile, du->unit, No);
- f_close(ofile);
- du->filed= Yes;
- return Yes;
- }
- }
- }
-
- Hidden intlet
- err_line(pname)
- value pname;
- {
- if (errlino == 0 || erruname == Vnil || compare(erruname, pname) != 0)
- return 0;
- else {
- intlet el= errlino;
- errlino= 0;
- return el;
- }
- }
-
- /************************** VALUES ***************************************/
- /* The permanent environment in the old format was kept as a single file */
- /* but this caused slow start ups if the file was big. */
- /* Thus the new version stores each permanent target on a separate file, */
- /* that furthermore is only loaded on demand. */
- /* To achieve this, a directory is kept of the permanent tags and their */
- /* file names. Care has to be taken that disaster occurring in */
- /* the middle of an update of this directory does the least harm. */
- /* Having the directory refer to a non-existent file is considered less */
- /* harmful than leaving a file around that can never be accessed, for */
- /* instance, so a file is deleted before its directory entry, */
- /* and so forth. */
- /*************************************************************************/
-
- Hidden bool
- t_exists(name, aa)
- value name, **aa;
- {
- return in_env(prmnv->tab, name, aa);
- }
-
- Hidden Procedure
- def_target(name, t)
- value name, t;
- {
- e_replace(t, &prmnv->tab, name);
- }
-
- Hidden Procedure
- free_target(name)
- value name;
- {
- e_delete(&prmnv->tab, name);
- }
-
- Hidden Procedure
- tarfiled(name, v)
- value name, v;
- {
- value p= mk_per(v);
- def_target(name, p);
- release(p);
- }
-
- Visible value
- tarvalue(name, v)
- value name, v;
- {
- value getval();
- if (Is_filed(v)) {
- per *p= Perm(v);
- if (p->val == Vnil) {
- value *aa, pname= permkey(name, Tar);
- if (!p_exists(pname, &aa))
- syserr(MESS(4015, "tarvalue"));
- release(pname);
- p->val= getval(*aa, In_tarval);
- }
- return p->val;
- }
- return v;
- }
-
- Hidden value last_tname= Vnil; /*last edited target */
-
- Visible Procedure
- edit_target()
- {
- value name= Vnil; bool ens_tfiled();
- value fname;
- if (Ceol(tx)) {
- if (last_tname == Vnil)
- parerr(MESS(4016, "no current target"));
- else
- name= copy(last_tname);
- } else if (!is_tag(&name))
- parerr(MESS(4017, "I find nothing editible here"));
- if (still_ok && ens_tfiled(name, &fname)) {
- ed_target(name, fname);
- release(fname);
- }
- release(name);
- }
-
- Hidden char NO_T_WRITE[]=
- "you have no write permission in this workspace: you may not change the target\n\
- *** do you still want to display the target?";
-
- Hidden Procedure
- ed_target(name, fname)
- value name, fname;
- {
- /* Edit a target. The value in the target is written to the file,
- and then removed from the internal permanent environment so that
- if a syntax error occurs when reading the value back, the value is
- absent from the internal permanent environment.
- Thus when editing the file to correct the syntax error, the
- file doesn't get overwritten.
- The contents may be completely deleted in which case the target is
- deleted.
- */
- value v, getval();
- if (!ws_writable() && !is_intended(NO_T_WRITE)) return;
- #ifndef INTEGRATION
- f_edit(fname, 0);
- #else
- f_edit(fname, 0, tar_prompt);
- #endif
- if (!still_there(fname)) {
- value pname= permkey(name, Tar);
- free_target(name);
- free_perm(pname);
- release(pname);
- release(last_tname); last_tname= Vnil;
- return;
- }
- release(last_tname); last_tname= copy(name);
- fclose(ifile); /*since still_there leaves it open*/
- v= getval(fname, In_edval);
- if (still_ok) def_target(name, v);
- release(v);
- }
-
- Hidden bool
- ens_tfiled(name, fname)
- value name, *fname;
- {
- value *aa;
- if (!t_exists(name, &aa)) {
- pprerr(MESS(4018, "no such target in this workspace"));
- return No;
- } else {
- value pname= permkey(name, Tar);
- *fname= get_fname(pname);
- if (!Is_filed(*aa)) {
- putval(*fname, *aa, No);
- tarfiled(name, *aa);
- }
- release(pname);
- return Yes;
- }
- }
-
- /***************************** Values on files ****************************/
-
- Hidden value
- getval(fname, ct)
- value fname;
- literal ct; /* context */
- {
- char *buf= Nil; int k; parsetree e, code; value v= Vnil;
- ifile= fopen(strval(fname), "r");
- if (ifile) {
- txptr fcol_save= first_col, tx_save= tx; context c;
- sv_context(&c);
- cntxt= ct;
- buf= getmem((unsigned)(f_size(ifile)+2)*sizeof(char));
- if (buf == Nil)
- syserr(MESS(4019, "can't get buffer to read file"));
- first_col= tx= ceol= buf;
- while ((k= getc(ifile)) != EOF)
- if (k != '\n') *ceol++= k;
- *ceol= '\n';
- fclose(ifile); vs_ifile();
- e= expr(ceol);
- if (still_ok) fix_nodes(&e, &code);
- curline=e; curlino= one;
- v= evalthread(code); curline= Vnil;
- release(e);
- if (buf != Nil) freemem((ptr) buf);
- set_context(&c);
- first_col= fcol_save; tx= tx_save;
- } else {
- error(CANT_READ);
- vs_ifile();
- }
- return v;
- }
-
- Visible Procedure
- getprmnv()
- {
- intlet k, len; value name, fname; literal type;
- if (f_exists(BPERMFILE)) {
- value fn;
- fn= mk_text(BPERMFILE);
- b_perm= getval(fn, In_prmnv);
- release(fn);
- if (!still_ok) exit(1);
- len= length(b_perm);
- k_Over_len {
- p_name_type(*key(b_perm, k), &name, &type);
- if (type == Tar) tarfiled(name, Vnil);
- fname= copy(*assoc(b_perm, k));
- insert(fname, &file_names);
- release(fname); release(name);
- }
- } else
- b_perm= mk_elt();
-
- #ifdef CONVERSION
- if (f_exists(PRMNVFILE)) { /* convert from old to new format */
- value tab, v, pname, new_fname();
- value fn= mk_text(PRMNVFILE), save= mk_text(SAVEPRMNVFILE);
- tab= getval(fn, In_prmnv);
- if (!still_ok) exit(1);
- len= length(tab);
- k_Over_len {
- name= copy(*key(tab, k));
- v= copy(*assoc(tab, k));
- def_target(name, v);
- pname= permkey(name, Tar);
- fname= get_fname(pname);
- putval(fname, v, Yes);
- tarfiled(name, v);
- release(name); release(v); release(fname);
- release(pname);
- }
- f_rename(fn, save);
- if (len > 0)
- printf("*** [Old permanent environment converted]\n");
- release(tab); release(fn); release(save);
- }
- #endif CONVERSION
- }
-
- Hidden Procedure
- putval(fname, v, silently)
- value fname, v; bool silently;
- {
- FILE *ofile; value fn= mk_text(tempfile); bool was_ok= still_ok;
- ofile= fopen(strval(fn), "w");
- if (ofile != NULL) {
- redirect(ofile);
- still_ok= Yes;
- wri(v, No, No, Yes); newline();
- f_close(ofile);
- redirect(stdout);
- if (still_ok) f_rename(fn, fname);
- } else if (!silently) error(CANT_WRITE);
- still_ok= was_ok;
- release(fn);
- }
-
- Visible Procedure
- putprmnv()
- {
- static bool active;
- value v, name, fname, fn, *aa, pname; literal type;
- int k, len;
- if (active) return;
- active= Yes;
- len= length(b_perm);
- for (k= len-1; k>=0; --k) {
- p_name_type(*key(b_perm, k), &name, &type);
- if (type == Tar && !t_exists(name, &aa))
- free_perm(*key(b_perm, k));
- release(name);
- }
- len= length(prmnv->tab);
- k_Over_len {
- v= copy(*assoc(prmnv->tab, k));
- if (!Is_filed(v)) {
- name= copy(*key(prmnv->tab, k));
- pname= permkey(name, Tar);
- fname= get_fname(pname);
- putval(fname, v, Yes);
- tarfiled(name, v);
- release(name); release(fname); release(pname);
- }
- release(v);
- }
- fn= mk_text(BPERMFILE);
- putval(fn, b_perm, Yes);
- /* Remove the file if the permanent environment is empty */
- if (length(b_perm) == 0) f_delete(fn);
- release(fn);
- active= No;
- }
-
- Visible Procedure
- initsou()
- {
- b_units= mk_elt();
- file_names= mk_elt();
- }
-
- Visible Procedure
- endsou()
- {
- /* Release everything around so "memory leakage" can be detected */
- release(b_units); b_units= Vnil;
- release(b_perm); b_perm= Vnil;
- release(file_names); file_names= Vnil;
- release(last_tname); last_tname= Vnil;
- }
-
- Visible Procedure
- lst_uhds()
- {
- intlet k, len= length(b_perm); int c;
- value name; literal type;
- k_Over_len {
- p_name_type(*key(b_perm, k), &name, &type);
- if (type != Tar) {
- FILE *fn= fopen(strval(*assoc(b_perm, k)), "r");
- if (fn) {
- while ((c= getc(fn)) != EOF && c != '\n')
- putc(c, stdout);
- putc('\n', stdout);
- fclose(fn);
- }
- }
- release(name);
- }
- len= length(b_units);
- k_Over_len {
- how *u= How_to(*assoc(b_units, k));
- #ifndef TRY
- value *aa;
- if (u -> filed == No && !p_exists(*key(b_units, k), &aa))
- #else
- if (u -> filed == No)
- #endif
- display(stdout, u -> unit, Yes);
- }
- fflush(stdout);
- }
-